package qinyi365;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;

/**
 * 地址经纬度信息获取工具类
 * 
 * @author liuw
 * @create date 2010/01/18
 */
public class AddressLatLngUtil {
	private  final String REQUEST_ENCODE = "UTF-8";
	private  final String ADDRESS_KEY = "\"address\"";
	private  final String ADDRESS_COUNTRY_KEY = "\"CountryName\"";
	private  final String ADDRESS_REGION_KEY = "\"AdministrativeAreaName\"";
	private  final String ADDRESS_CITY_KEY = "\"LocalityName\"";
	private  final String ADDRESS_POINT_KEY = "\"coordinates\"";
	private  final String ADDRESS_SPLIT_STR = ":";

	private  final String LOCATION_COUNTRY_KEY = "\"country\"";
	private  final String LOCATION_REGION_KEY = "\"region\"";
	private  final String LOCATION_CITY_KEY = "\"city\"";
	// private  final String LOCATION_POINT_KEY = "\"location\"";
	private  final String LOCATION_POINT_LATITUDE_KEY = "\"latitude\"";
	private  final String LOCATION_POINT_LONGITUDE_KEY = "\"longitude\"";
	private  final String LOCATION_POINT_PRECISIONY_KEY = "\"accuracy\"";
	private  final String LOCATION_SPLIT_STR = ",";

	public  final int MIN_ZOOM = 11;
	public  final int MAX_ZOOM = 18;

	private  final int DOWNNUM_FOR_PROXY = 8000;
	private  final int CONNECT_TIMEOUT = 30000; // 30秒
	private  final int THREAD_SLEEP_MILLIS = 200;
	private  boolean flag = false;
	private  int downNum = 0;

	private  String proxyHost = "165.228.128.10";
	private  String proxyPort = "3128";
	private  String proxySet = "true";

	private  final Logger logger = Logger
			.getLogger(AddressLatLngUtil.class);
	public  Point getPointFromAddress(String address)
	{
		String spi = "小区,楼,街,大厦,局,镇,弄,院,学,号,村,大道";
		String spis[] = spi.split(",");
		for(String str:spis)
		{
			if(address.contains(str))
			{
				address = address.substring(0,address.indexOf(str) + str.length());
				break;
			}
		}
		
		
		
		List<String> sp = new ArrayList<String>();
		sp.add("");
 		 Map<String, Points> map = getAddressxy(address);
		 Points p = null;
		 if(map != null)
		 {
			 Iterator<String> keys = map.keySet().iterator();
			 while(keys.hasNext())
			 {
				 String key = keys.next();
				  p = map.get(key);
				  if(p!= null)
					  break;
			 }
		 }
		 
		 Point point = null;
		 if(p != null)
		 {
		 DecimalFormat df = new DecimalFormat("0.000000");
		 point  = new Point(Double.valueOf(df.format(p.getLongitude())), 
				 Double.valueOf(df.format(p.getLatitude())));
		 }else
		 {
			 System.out.println("address" + address);
		 }
		 return point;
	}
	
	/**
	 * 获取地址详细信息及经纬度信息
	 * 
	 * @param address
	 * @return Map<地址, 经纬度>
	 */
	public  Map<String, Points> getAddressxy(String address) {
		StringBuilder urlBuilder = new StringBuilder();
		urlBuilder.append("http://ditu.google.cn/maps/geo");
		urlBuilder.append("?output=json");
		urlBuilder.append("&oe=utf-8");
		urlBuilder.append("&q=").append(encodeURLForUTF8(address));
		urlBuilder
				.append("&key=ABQIAAAAzr2EBOXUKnm_jVnk0OJI7xSosDVG8KKPE1-m51RBrvYughuyMxQ-i1QfUnH94QxWIa6N4U6MouMmBA");
		urlBuilder.append("&mapclient=jsapi");
		urlBuilder.append("&hl=zh-CN");
		urlBuilder.append("&callback=_xdc_._1g4gm5mh3");
		// logger.info(urlBuilder.toString());
		HttpURLConnection httpConnection = null;
		try {
			// 1、构造HttpURLConnection连接
			URL url = new URL(urlBuilder.toString());
			URLConnection urlConnection = url.openConnection();
			httpConnection = (HttpURLConnection) urlConnection;
			httpConnection.setDoInput(true);
			httpConnection.setDoOutput(true);
			httpConnection.setConnectTimeout(CONNECT_TIMEOUT);
			httpConnection.connect();

			// 2、接收响应结果
			InputStream inStream = httpConnection.getInputStream();
			String htmlContent = getContentByStream(inStream, REQUEST_ENCODE);
			// 关闭流资源
			inStream.close();

			// 3、解析结果
			Map<String, Points> map = parseAddressLatLng(htmlContent);
			updateProxy();
			return map;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.error("===========获取经纬度信息异常！请求地址：" + address, e);
			return java.util.Collections.emptyMap();
		} finally {
			// 关闭连接
			if (null != httpConnection) {
				httpConnection.disconnect();
			}
		}
	}
	
	
	/**
	 * 获取地址详细信息及经纬度信息
	 * 
	 * @param address
	 * @return Map<地址, 经纬度>
	 */
	public  Map<String, Points> getAddressLatLng(String address) {
		StringBuilder urlBuilder = new StringBuilder();
		urlBuilder.append("http://ditu.google.cn/maps/geo");
		urlBuilder.append("?output=json");
		urlBuilder.append("&oe=utf-8");
		urlBuilder.append("&q=").append(encodeURLForUTF8(address));
		urlBuilder
				.append("&key=ABQIAAAAzr2EBOXUKnm_jVnk0OJI7xSosDVG8KKPE1-m51RBrvYughuyMxQ-i1QfUnH94QxWIa6N4U6MouMmBA");
		urlBuilder.append("&mapclient=jsapi");
		urlBuilder.append("&hl=zh-CN");
		urlBuilder.append("&callback=_xdc_._1g4gm5mh3");
		// logger.info(urlBuilder.toString());
		HttpURLConnection httpConnection = null;
		try {
			// 1、构造HttpURLConnection连接
			URL url = new URL(urlBuilder.toString());
			URLConnection urlConnection = url.openConnection();
			httpConnection = (HttpURLConnection) urlConnection;
			httpConnection.setDoInput(true);
			httpConnection.setDoOutput(true);
			httpConnection.setConnectTimeout(CONNECT_TIMEOUT);
			httpConnection.connect();

			// 2、接收响应结果
			InputStream inStream = httpConnection.getInputStream();
			String htmlContent = getContentByStream(inStream, REQUEST_ENCODE);
			// 关闭流资源
			inStream.close();

			// 3、解析结果
			Map<String, Points> map = parseAddressLatLng(htmlContent);
			updateProxy();
			return map;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.error("===========获取经纬度信息异常！请求地址：" + address, e);
			return java.util.Collections.emptyMap();
		} finally {
			// 关闭连接
			if (null != httpConnection) {
				httpConnection.disconnect();
			}
		}
	}

	/**
	 * 根据地址信息获取经纬度
	 * 
	 * @param addressList
	 *            地址集合
	 * @return List<Map<地址, 经纬度对象>>
	 */
	public  List<Map<String, Points>> getAddressLatLng(
			List<String> addressList) {
		List<Map<String, Points>> list = new ArrayList<Map<String, Points>>();
		if (null == addressList || addressList.isEmpty()) {
			return list;
		}

		for (String address : addressList) {
			try {
				// 休息一下
				Thread.sleep(THREAD_SLEEP_MILLIS);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			Map<String, Points> addrMap = getAddressLatLng(address);
			if (false == addrMap.isEmpty()) {
				list.add(addrMap);
			} else {
				// System.out.println(address + " Points is null!!!");
				logger.warn("===========获取经纬度信息为空！请求地址：" + address);
			}
		}
		return list;
	}

	/**
	 * 解析网页内容地址信息及经纬度信息
	 * 
	 * @param htmlContent
	 * @return Map<地址, 经纬度>
	 */
	private  Map<String, Points> parseAddressLatLng(String htmlContent) {
		Map<String, Points> addr = new HashMap<String, Points>(1);
		if (isNullOrEmpty(htmlContent)) {
			return addr;
		}

		String[] contents = htmlContent.split("\r\n");
		String[] ss = null;
		String address = null;
		String country = null;
		String region = null;
		String city = null;
		Points Points = null;
		for (String line : contents) {
			if (isNullOrEmpty(line)) {
				continue;
			}
			line = line.trim();
			if (line.contains(ADDRESS_POINT_KEY)) {
				/*
				 * "coordinates": [ 113.9465830, 22.5309650, 0 ]
				 */
				ss = line.split(ADDRESS_SPLIT_STR);
				if (null != ss && ss.length > 1) {
					String pointStr = getMiddleStr(ss[1], "[", "]");
					String[] pss = pointStr.split(",");
					if (null != pss && pss.length > 1) {
						double defaultValue = 0D;
						Points = new Points(isNullOrEmpty(pss[0]) ? defaultValue
								: Double.parseDouble(pss[0].trim()),
								isNullOrEmpty(pss[1]) ? defaultValue : Double
										.parseDouble(pss[1].trim()));
					}
				}
			} else if (line.contains(ADDRESS_KEY)) {
				address = getValue(line, ADDRESS_KEY);
			} else if (line.contains(ADDRESS_COUNTRY_KEY)) {
				country = getValue(line, ADDRESS_COUNTRY_KEY);
			} else if (line.contains(ADDRESS_REGION_KEY)) {
				region = getValue(line, ADDRESS_REGION_KEY);
			} else if (line.contains(ADDRESS_CITY_KEY)) {
				city = getValue(line, ADDRESS_CITY_KEY);
			}

			// 默认取第一个地址信息
			if (false == isNullOrEmpty(address) && null != Points) {
				Points.setCountry(country);
				Points.setRegion(region);
				Points.setCity(city);
				break;
			}
		} // end-for-contents

		// 如果地址不为空
		if (false == isNullOrEmpty(address)) {
			addr.put(address, Points);
		}
		return addr;
	}

	/**
	 * 获取中间字符串内容
	 * 
	 * @param content
	 * @param beginStr
	 * @param endStr
	 * @return
	 */
	private  String getMiddleStr(String content, String beginStr,
			String endStr) {
		String str = "";
		if (isNullOrEmpty(content)) {
			return str;
		}

		content = content.trim();
		int bIndex = content.indexOf(beginStr);
		int eIndex = -1;
		if (null != beginStr && beginStr.equals(endStr)) {
			int index = content.substring(bIndex + beginStr.length()).indexOf(
					endStr);
			eIndex = content.substring(0, bIndex + beginStr.length()).length()
					+ index;
		} else if (null != endStr && false == endStr.equals(beginStr)) {
			eIndex = content.indexOf(endStr);
		}

		if (-1 != bIndex && -1 != eIndex) {
			str = content.substring(bIndex + beginStr.length(), eIndex);
		}
		return str;
	}

	private  final String PROXY_HOST_KEY = "http.proxyHost";
	private  final String PROXY_PORT_KEY = "http.proxyPort";
	private  final String PROXY_SET_KEY = "http.proxySet";

	/**
	 * 切换代理
	 */
	private  synchronized void updateProxy() {
		downNum++;
		if (downNum % DOWNNUM_FOR_PROXY == 0) {
			if (flag) {
				clearProxy();
				flag = false;
			} else {
				setProxy();
				flag = true;
			}
		}
	}

	private  void setProxy() {
		System.setProperty(PROXY_HOST_KEY, proxyHost);
		System.setProperty(PROXY_PORT_KEY, proxyPort);
		System.setProperty(PROXY_SET_KEY, proxySet);

		logger.info("setProxy=====" + proxyHost + ":" + proxyPort);
		// System.out.println("setProxy====="+proxyHost+":"+proxyPort);
	}

	private  void clearProxy() {
		System.clearProperty(PROXY_HOST_KEY);
		System.clearProperty(PROXY_PORT_KEY);
		System.clearProperty(PROXY_SET_KEY);

		logger.info("clearProxy=====");
		// System.out.println("clearProxy=====");
	}

	private  String encodeURLForUTF8(String str) {
		try {
			str = java.net.URLEncoder.encode(str, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.error("字符串转码异常，字符串：" + str, e);
		}
		return str;
	}

	/**
	 * 按照指定编码从流中读取信息
	 * 
	 * @param inStream
	 * @param encode
	 * @return
	 * @throws IOException
	 */
	private  String getContentByStream(InputStream inStream, String encode)
			throws IOException {
		if (null == inStream) {
			return null;
		}

		StringBuilder content = new StringBuilder();
		// 采用指定编码格式读取流内容
		BufferedReader reader = new BufferedReader(new InputStreamReader(
				inStream, encode));
		String message = null;
		while (null != (message = reader.readLine())) {
			content.append(message);
			content.append("\r\n");
		}
		// 关闭读取器，释放资源
		reader.close();
		return (content.toString());
	}

	/**
	 * 获取偏移后的经纬度（Google中国地图偏移接口） 中国地图和卫星图都存在偏移量，这个是由中国规划局确定的，
	 * google的地图服务，以ditu.gogle开头的都没有偏差，以maps.google开头的服务就有偏差
	 * 
	 * @param zoom
	 *            偏移级别（从11级到18级，18级最精确）
	 * @param sourcePoint
	 *            经纬度对象
	 * @return
	 */
	public  Points getOffsetLatLng(int zoom, Points sourcePoint) {
		if (null == sourcePoint) {
			return null;
		}

		StringBuilder urlBuilder = new StringBuilder();
		urlBuilder.append("http://ditu.google.cn/maps/vp");
		urlBuilder.append("?spn=0.0,0.0");
		urlBuilder.append("&z=").append(zoom);
		urlBuilder.append("&vp=");
		urlBuilder.append(sourcePoint.getLatitude());// 纬度
		urlBuilder.append(",");
		urlBuilder.append(sourcePoint.getLongitude());// 经度
		HttpURLConnection httpConnection = null;
		try {
			// 1、构造HttpURLConnection连接
			URL url = new URL(urlBuilder.toString());
			URLConnection urlConnection = url.openConnection();
			httpConnection = (HttpURLConnection) urlConnection;
			httpConnection.setDoInput(true);
			httpConnection.setDoOutput(true);
			httpConnection.setConnectTimeout(CONNECT_TIMEOUT);
			httpConnection.connect();
			// 2、接收响应结果
			InputStream inStream = httpConnection.getInputStream();
			String htmlContent = getContentByStream(inStream, REQUEST_ENCODE);
			// 关闭流资源
			inStream.close();
			// 3、解析结果
			String offset = parseOffsetFromZoom(zoom, htmlContent);
			// 如果没有偏移值，则返回原经纬度对象
			if (isNullOrEmpty(offset)) {
				return sourcePoint;
			}
			Points targetPoint = getOffsetPoint(offset, zoom, sourcePoint);
			updateProxy();

			logger.info("sourcePoint: " + sourcePoint);
			logger.info("targetPoint: " + targetPoint);

			return targetPoint;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.error("===========获取偏移经纬度信息异常！zoom = " + zoom
					+ ", sourcePoint = " + sourcePoint, e);
		} finally {
			// 关闭连接
			if (null != httpConnection) {
				httpConnection.disconnect();
			}
		}
		return null;
	}

	/**
	 * 获取对应级别像素偏移量
	 * 
	 * @param zoom
	 * @param htmlContent
	 * @return
	 */
	private  String parseOffsetFromZoom(int zoom, String htmlContent) {
		String offset = null;
		if (isNullOrEmpty(htmlContent) || zoom > MAX_ZOOM || zoom < MIN_ZOOM) {
			return offset;
		}
		/*
		 * 下面分别表示经纬度、级别、偏移像素数量【级别从11级到18级，共8组数字】
		 * 前一组数字精确的等于后一组数字除二，我们为了得到最精确的偏移，故选择第18级的偏移量1193，-270，
		 * 1193为x方向上精度的偏移像素，-270为y方向上维度偏移像素
		 * 
		 * window.GTileShiftUpdateOffset && window.GTileShiftUpdateOffset(
		 * 39.111195, 117.148067, 18, [9, -2, 18, -4, 37, -8, 74, -16, 149, -33,
		 * 298, -67, 596, -135, 1193, -270]);
		 */
		int beginIndex = htmlContent.lastIndexOf("[");
		int endIndex = htmlContent.lastIndexOf("]");
		if (beginIndex > 0 && endIndex > 0) {
			// 获取各级别像素偏移量内容
			String content = htmlContent.substring(beginIndex + 1, endIndex);
			offset = getOffsetByZoom(zoom, content);
		}
		return offset;
	}

	/**
	 * 获取zoom级别的像素偏移量
	 * 
	 * @param zoom
	 * @param content
	 * @return
	 */
	private  String getOffsetByZoom(int zoom, String content) {
		String[] ss = content.split(",");
		int index = ((zoom - 10) << 1) - 2;
		if (null == ss || ss.length < (index + 1)) {
			return null;
		}
		return (ss[index].trim() + "," + ss[index + 1].trim());
	}

	/**
	 * 获取校正后的经纬度
	 * 
	 * @param offset
	 * @param zoom
	 * @param Points
	 * @return
	 */
	private  Points getOffsetPoint(String offset, int zoom, Points Points) {
		String[] ss = offset.split(",");
		int offsetX = Integer.parseInt(ss[0]);
		int offsetY = Integer.parseInt(ss[1]);

		double lngPixel = (Math.round(lngToPixel(Points.getLongitude(), zoom)) - offsetX);
		double latPixel = (Math.round(latToPixel(Points.getLatitude(), zoom)) - offsetY);
		return new Points(pixelToLng(lngPixel, zoom), pixelToLat(latPixel, zoom));
	}

	/*
	 * sinLatitude = sin(latitude * pi/180)
	 * 
	 * pixelX = ((longitude + 180) / 360) * 256 * 2level
	 * 
	 * pixelY = (0.5 � log((1 + sinLatitude) / (1 � sinLatitude)) / (4 * pi)) *
	 * 256 * 2level
	 */

	/**
	 * 经度到像素X值
	 * 
	 * @param lng
	 * @param zoom
	 * @return
	 */
	private  double lngToPixel(double lng, int zoom) {
		return (lng + 180) * (256L << zoom) / 360;
	}

	/**
	 * 纬度到像素Y
	 * 
	 * @param lat
	 * @param zoom
	 * @return
	 */
	private  double latToPixel(double lat, int zoom) {
		double siny = Math.sin(lat * Math.PI / 180);
		double y = Math.log((1 + siny) / (1 - siny));
		return (256L << zoom) * (0.5 - y / (4 * Math.PI));
	}

	/**
	 * 像素X到经度
	 * 
	 * @param pixelX
	 * @param zoom
	 * @return
	 */
	private  double pixelToLng(double pixelX, int zoom) {
		return pixelX * 360 / (256L << zoom) - 180;
	}

	/**
	 * 像素Y到纬度
	 * 
	 * @param pixelY
	 * @param zoom
	 * @return
	 */
	private  double pixelToLat(double pixelY, int zoom) {
		double y = 4 * Math.PI * (0.5 - pixelY / (256L << zoom));
		double z = Math.pow(Math.E, y);
		double siny = (z - 1) / (z + 1);
		return Math.asin(siny) * 180 / Math.PI;
	}

	/**
	 * 根据地区编码（LAC）和基站编号（CID）获取经纬度信息
	 * 
	 * @param lac
	 *            地区编码
	 * @param cellId
	 *            基站编号
	 * @deprecated 改为调用 getLocationByLacAndCid方法
	 * @return
	 */
	public  Points getLatLngByLacAndCid(int lac, int cellId) {
		String urlString = "http://www.google.com/glm/mmap";
		HttpURLConnection httpConn = null;
		try {
			// ---open a connection to Google Maps API---
			URL url = new URL(urlString);
			URLConnection conn = url.openConnection();
			httpConn = (HttpURLConnection) conn;
			httpConn.setDoOutput(true);
			httpConn.setDoInput(true);
			httpConn.setDefaultUseCaches(false);
			httpConn.setRequestMethod("POST");
			httpConn.setConnectTimeout(CONNECT_TIMEOUT);
			httpConn.connect();
			// ---write some custom data to Google Maps API---
			OutputStream outputStream = httpConn.getOutputStream();
			writeData(outputStream, cellId, lac);
			outputStream.close();
			// ---get the response---
			DataInputStream dataInputStream = new DataInputStream(httpConn
					.getInputStream());
			// ---interpret the response obtained---
			dataInputStream.readShort();
			dataInputStream.readByte();
			int code = dataInputStream.readInt();
			Points Points = null;
			if (code == 0) {
				double lat = (double) dataInputStream.readInt() / 1000000D;
				double lng = (double) dataInputStream.readInt() / 1000000D;
				int i = dataInputStream.readInt();
				int j = dataInputStream.readInt();
				String s = dataInputStream.readUTF();
				// 关闭流
				dataInputStream.close();

				// 包装结果
				Points = new Points(lng, lat);
				Points.setPrecision(i); // 精确度

				// ---display Google Maps---
				// logger.info("lac = "+lac+", cellId = "+cellId+", Latitude = "+lat+", Longitude = "+lng
				// + ", precision = "+i+", j = "+j+", s = "+s);
				// System.out.println("Latitude = " + lat + ", Longitude = " +
				// lng
				// + ", precision = " + i + ", j = " + j + ", s = " + s);
			} else {
				logger.warn("===========根据地区编码和基站编号获取经纬度信息失败！lac = " + lac
						+ ", cellId = " + cellId);
			}

			return Points;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.error("===========根据地区编码和基站编号获取经纬度信息异常！lac = " + lac
					+ ", cellId = " + cellId, e);
		} finally {
			// 关闭连接
			if (null != httpConn) {
				httpConn.disconnect();
			}
		}
		return null;
	}

	private  void writeData(OutputStream out, int cellId, int lac)
			throws IOException {
		DataOutputStream dataOutputStream = new DataOutputStream(out);
		dataOutputStream.writeShort(21);
		dataOutputStream.writeLong(0);
		dataOutputStream.writeUTF("en");
		dataOutputStream.writeUTF("Android");
		dataOutputStream.writeUTF("1.0");
		dataOutputStream.writeUTF("Web");
		dataOutputStream.writeByte(27);
		dataOutputStream.writeInt(0);
		dataOutputStream.writeInt(0);
		if (cellId >= 65536) {
			// 联通3G
			dataOutputStream.writeInt(5);
		} else {
			// 移动3G
			dataOutputStream.writeInt(3);
		}
		dataOutputStream.writeUTF("");

		dataOutputStream.writeInt(cellId);
		dataOutputStream.writeInt(lac);

		dataOutputStream.writeInt(0); // mnc
		dataOutputStream.writeInt(0); // mcc
		dataOutputStream.writeInt(0);
		dataOutputStream.writeInt(0);
		dataOutputStream.flush();
		dataOutputStream.close();
	}

	/**
	 * 根据地区编码（LAC）和基站编号（CID）获取地区信息
	 * 
	 * @param lac
	 *            地区编码
	 * @param cellId
	 *            基站编号
	 * @return
	 */
	public  Points getLocationByLacAndCid(int lac, int cellId) {
		String urlString = "http://www.google.cn/loc/json";
		HttpURLConnection httpConn = null;
		try {
			// ---open a connection to Google Maps API---
			URL url = new URL(urlString);
			URLConnection conn = url.openConnection();
			httpConn = (HttpURLConnection) conn;
			httpConn.setDoOutput(true);
			httpConn.setDoInput(true);
			httpConn.setDefaultUseCaches(false);
			httpConn.setRequestMethod("POST");
			httpConn.setRequestProperty("Content-Type", "application/json");
			httpConn.setConnectTimeout(CONNECT_TIMEOUT);
			httpConn.connect();
			// ---write some custom data to Google Maps API---
			OutputStreamWriter outputStream = new OutputStreamWriter(httpConn
					.getOutputStream());
			outputStream.write(getLocationRequest(lac, cellId));
			outputStream.flush();
			outputStream.close();
			// ---get the response---
			String responseContent = getContentByStream(httpConn
					.getInputStream(), REQUEST_ENCODE);
			// ---interpret the response obtained---
			Points Points = parseLocationContent(responseContent);

			// logger.info(responseContent);
			return Points;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.error("===========根据地区编码和基站编号获取地区信息异常！lac = " + lac
					+ ", cellId = " + cellId, e);
		} finally {
			// 关闭连接
			if (null != httpConn) {
				httpConn.disconnect();
			}
		}
		return null;
	}

	private  String getLocationRequest(int lac, int cellId) {
		StringBuilder requestContent = new StringBuilder();
		requestContent.append("{ ");
		requestContent.append(" \"version\" : \"1.1.0\", ");
		requestContent.append(" \"host\" : \"ditu.google.cn\", ");
		requestContent
				.append(" \"access_token\" : \"2:k7j3G6LaL6u_lafw:4iXOeOpTh1glSXe\", ");
		requestContent.append(" \"request_address\" : true,");
		requestContent.append(" \"cell_towers\" : ");
		requestContent.append(" [ ");
		requestContent.append(" { ");
		requestContent.append(" \"cell_id\" : ").append(cellId).append(", ");
		requestContent.append(" \"location_area_code\" : ").append(lac).append(
				", ");
		requestContent.append(" \"mobile_country_code\" : 460, ");
		requestContent.append(" \"mobile_network_code\" : 00, ");
		requestContent.append(" \"age\" : 0, ");
		requestContent.append(" \"signal_strength\" : -60, ");
		requestContent.append(" \"timing_advance\" : 5555 ");
		requestContent.append(" } ");
		requestContent.append(" ] ");
		requestContent.append("} ");
		return (requestContent.toString());
	}

	/**
	 * 解析地区信息，并构造Point对象
	 * 
	 * @param respContent
	 * @return
	 */
	private  Points parseLocationContent(String respContent) {
		if (isNullOrEmpty(respContent)) {
			return null;
		}
		/*
		 * {"location":{"latitude":31.148662,"longitude":114.957975,
		 * "address":{"country"
		 * :"中国","country_code":"CN","region":"湖北省","city":"黄冈市"},
		 * "accuracy":1625.0},
		 * "access_token":"2:i1-PwttBtQsSyYvX:VVq7Nsl89ut7l9aV"}
		 */
		// 获取纬度、经度、精确度、国家、省份、城市信息
		String latitude = getValue(respContent, LOCATION_POINT_LATITUDE_KEY);
		String longitude = getValue(respContent, LOCATION_POINT_LONGITUDE_KEY);
		String precisiony = getValue(respContent, LOCATION_POINT_PRECISIONY_KEY);
		String country = getValue(respContent, LOCATION_COUNTRY_KEY);
		String region = getValue(respContent, LOCATION_REGION_KEY);
		String city = getValue(respContent, LOCATION_CITY_KEY);
		Points Points = null;
		if (false == isNullOrEmpty(latitude)
				&& false == isNullOrEmpty(longitude)) {
			Points = new Points(Double.parseDouble(longitude), Double
					.parseDouble(latitude));
			if (false == isNullOrEmpty(precisiony)) {
				Points.setPrecision(Double.parseDouble(precisiony));
			}
			Points.setCountry(country);
			Points.setRegion(region);
			Points.setCity(city);
		}
		return Points;
	}

	private  String getValue(String content, String key) {
		if (false == isNullOrEmpty(content) && false == isNullOrEmpty(key)) {
			String[] ss = content.split("\r\n");
			for (String line : ss) {
				if (isNullOrEmpty(line)) {
					continue;
				}

				line = line.replace("{", "").replace("}", "").replace("[", "")
						.replace("]", "").trim();
				String[] sss = line.split(LOCATION_SPLIT_STR);
				for (String str : sss) {
					if (isNullOrEmpty(str) || false == str.contains(key)) {
						continue;
					}

					String[] sub = str.split(ADDRESS_SPLIT_STR);
					for (int i = 0; i < sub.length; i++) {
						if (isNullOrEmpty(sub[i])) {
							continue;
						}
						sub[i] = sub[i].trim();
					}
					List<String> subList = java.util.Arrays.asList(sub);
					int subIndex = subList.indexOf(key);
					if (-1 != subIndex && subList.size() > (subIndex + 1)) {
						String value = subList.get(subIndex + 1);
						return (value.replace("\"", "").trim());
					}
				}// end-for-sss

			}// end-for-ss
		}
		return null;
	}

	/**
	 * 判断字符串是否为空
	 * 
	 * @param str
	 * @return
	 */
	public  boolean isNullOrEmpty(String str) {
		if (null == str || "".equals(str)) {
			return true;
		}
		return false;
	}

	/**
	 * 经纬度坐标信息
	 */
	public  class Points {
		/**
		 * 经度
		 */
		private double longitude;

		/**
		 * 纬度
		 */
		private double latitude;

		/**
		 * 精确度
		 */
		private double precision;

		/**
		 * 国家
		 */
		private String country;

		/**
		 * 省份
		 */
		private String region;

		/**
		 * 城市
		 */
		private String city;

		/**
		 * 构造函数
		 * 
		 * @param longitude
		 *            经度
		 * @param latitude
		 *            纬度
		 */
		public Points(double longitude, double latitude) {
			this.longitude = longitude;
			this.latitude = latitude;
		}

		public double getLongitude() {
			return longitude;
		}

		public void setLongitude(double longitude) {
			this.longitude = longitude;
		}

		public double getLatitude() {
			return latitude;
		}

		public void setLatitude(double latitude) {
			this.latitude = latitude;
		}

		public double getPrecision() {
			return precision;
		}

		public void setPrecision(double precision) {
			this.precision = precision;
		}

		public String toString() {
			StringBuilder content = new StringBuilder();
			content.append(getClass().getName());
			content.append("[ latitude=");
			content.append(this.latitude);
			content.append(", longitude=");
			content.append(this.longitude);
			if (this.precision != 0.0) {
				content.append(", precision=");
				content.append(this.precision);
			}

			if (false == isNullOrEmpty(this.country)) {
				content.append(", country=");
				content.append(this.country);
			}

			if (false == isNullOrEmpty(this.region)) {
				content.append(", region=");
				content.append(this.region);
			}

			if (false == isNullOrEmpty(this.city)) {
				content.append(", city=");
				content.append(this.city);
			}
			content.append(" ]");
			return (content.toString());
		}

		public String getCountry() {
			return country;
		}

		public void setCountry(String country) {
			this.country = country;
		}

		public String getRegion() {
			return region;
		}

		public void setRegion(String region) {
			this.region = region;
		}

		public String getCity() {
			return city;
		}

		public void setCity(String city) {
			this.city = city;
		}
	}

	public  String getProxyHost() {
		return proxyHost;
	}

	public  void setProxyHost(String proxyHost) {
		proxyHost = proxyHost;
	}

	public  String getProxyPort() {
		return proxyPort;
	}

	public  void setProxyPort(String proxyPort) {
		proxyPort = proxyPort;
	}

	/**
	 * 测试
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		
		AddressLatLngUtil util = new AddressLatLngUtil();
		util.getPointFromAddress("中国北京北京市大兴区,北京经济技术开发区.东环中路5号.诺基亚通信有限公司");	
//		// System.getProperties().list(System.out);
//
//		// 深圳: (经度)lng:114.0578,(纬度)lat:22.5434
//		List<String> addrList = new ArrayList<String>();
//		addrList.add("留学生创业大厦");
//		// addrList.add("深圳市");
//		// addrList.add("世界之窗");
//		// addrList.add("地王大厦");
//		// addrList.add("黄鹤楼");
//
//		List<Map<String, Points>> list = getAddressLatLng(addrList);
//		for (Map<String, Points> map : list) {
//			for (Entry<String, Points> entry : map.entrySet()) {
//				logger.info(entry.getKey() + entry.getValue());
//
//				// 获取偏移坐标
//				Points offsetPoint = getOffsetLatLng(MAX_ZOOM, entry.getValue());
//				logger.info("偏移经纬度：" + offsetPoint);
//				System.out.println();
//			}
//		}
//
//		int lac = 0x717f;
//		int cellId = 0x3341;
//		Points Points = getLocationByLacAndCid(lac, cellId);
//		logger.info(Points);
//		Points = getOffsetLatLng(MAX_ZOOM, Points);
//		logger.info(Points);
//
//		System.out.println("finished!");

	}
}